/*
 * sigqueue_demo.c
 * gcc sigqueue_demo.c -o sigqueue_demo
 * ./sigqueue_demo
 * 父进程通过 sigqueue() 向子进程发送携带 整型数据 与 指针数据 的 SIGRTMIN 实时信号；子进程用 sigaction() + SA_SIGINFO 接收并解析数据。
 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

/* 子进程信号处理器 */
void handler(int sig, siginfo_t *info, void *ucontext)
{
    (void)ucontext;
    if (sig == SIGRTMIN) {
        printf("[Child %d] 收到信号 %d\n", getpid(), sig);

        /* 获取伴随数据 */
        int  val  = info->si_value.sival_int;
        void *ptr = info->si_value.sival_ptr;

        printf("        伴随整型 = %d\n", val);
        printf("        伴随指针 = %p\n", ptr);
    }
}

int main(void)
{
    pid_t pid = fork();
    if (pid < 0) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    /* -------- 子进程 -------- */
    if (pid == 0) {
        struct sigaction sa;
        sigemptyset(&sa.sa_mask);
        sa.sa_flags     = SA_SIGINFO;
        sa.sa_sigaction = handler;
        sigaction(SIGRTMIN, &sa, NULL);

        printf("[Child %d] 等待信号...\n", getpid());
        pause();                 /* 阻塞等待 */
        exit(EXIT_SUCCESS);
    }

    /* -------- 父进程 -------- */
    sleep(1);   /* 让子进程先装好 handler */

    union sigval value;
    value.sival_int = 12345;            /* 整型数据 */
    /* value.sival_ptr = (void *)0x12345678;  如需指针数据 */

    printf("[Parent %d] 向子进程 %d 发送 sigqueue...\n", getpid(), pid);
    if (sigqueue(pid, SIGRTMIN, value) == -1) {
        perror("sigqueue");
        exit(EXIT_FAILURE);
    }

    /* 等待子进程结束 */
    int status;
    waitpid(pid, &status, 0);
    printf("[Parent] 子进程已退出，status=%d\n", WEXITSTATUS(status));

    return 0;
}